package com.yyfax.infrastructure.base;

import android.app.Application;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.widget.Toast;
import com.yyfax.common.CLog;
import com.yyfax.infrastructure.network.NetworkReceiver;

import java.util.Locale;

/**
 * Created by HenryZhang on 16-10-27.
 * Copyright © 2016 www.yyfax.com. All Rights Reserved.
 */
public class BaseApplication {
	private static final String TAG = "BaseApplication";

	/**
	 * default value is base on 480*800 4.0inch screen
	 */
	public static int densityDpi = 240;
	public static float density = 1.5f;//scale
	public static float scaledDensity = 1.5f;//font scale
	public static int widthPixels = 480;
	public static int heightPixels = 800;
	public static float xDpi = 240.0f;
	public static float yDpi = 240.0f;

	public static String versionName;
	public static int versionCode;
	public static String channel = "";

	public static int mMainThreadId;
	public Handler mMainThreadHandler;

	protected Application mApplication;

	private static volatile BaseApplication mBaseInstance;//it is same object instance with mInstance where define in subclass

	public static BaseApplication getBaseInstance() {
		//1.lazy initialization, jvm will load inner class in first call. it is thread safe.
//		return InstanceHolder.instance;
		//2.set instance in constructor function
		if (mBaseInstance == null) {
			synchronized (BaseApplication.class) {
				if (mBaseInstance == null) {//todo only throw exception is the right choice, but i have no idea yet
					CLog.i(TAG, "initialize BaseApplication ...");
					mBaseInstance = new BaseApplication();
				}
			}
		}
		return mBaseInstance;
	}

	public static Application app() {
		return getBaseInstance().mApplication;
	}

	public void init(Application application) {
		mBaseInstance = this;
		mApplication = application;
		mMainThreadId = android.os.Process.myTid();
		CLog.e(TAG, "onCreate: uid=" + android.os.Process.myUid() +
				", supportsProcesses=" + android.os.Process.supportsProcesses() +
				", pid=" + android.os.Process.myPid() +
				", tid=" + mMainThreadId);
		mMainThreadHandler = new Handler();
		getDisplayMetrics(application);
		getPackageInfo(application);

		NetworkReceiver nr = new NetworkReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		application.registerReceiver(nr, filter);
	}

	public static boolean isRunInMainThread() {
		return android.os.Process.myTid() == mMainThreadId;
	}

	private void getDisplayMetrics(Application application) {
		DisplayMetrics dm = CUtility.getDisplayMetrics(application);
		densityDpi = dm.densityDpi;
		density = dm.density;
		scaledDensity = dm.scaledDensity;
		widthPixels = dm.widthPixels;
		heightPixels = dm.heightPixels;
		xDpi = dm.xdpi;
		yDpi = dm.ydpi;

		String desc = "densityDpi = " + densityDpi + ", scale = " + density + "; fontScale = " + scaledDensity + "; " + widthPixels + "*" + heightPixels + "; " + xDpi + "*" + yDpi;
		CLog.i(TAG, desc);
	}

	private void getPackageInfo(Application application) {
		try {
			PackageManager pm = application.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(application.getPackageName(), 0);
			versionName = pi.versionName;
			if (versionName == null || versionName.length() <= 0) {
				versionName = "1.0.0";
			}

			versionCode = pi.versionCode;
			if (versionCode == -1) {
				versionCode = 0;
			}
			ApplicationInfo appInfo = application.getPackageManager().getApplicationInfo(application.getPackageName(), PackageManager.GET_META_DATA);
			channel = appInfo.metaData.getString("UMENG_CHANNEL");
			CLog.i(TAG, "获取channel=" + channel + ";versionCode=" + versionCode + "'versionName=" + versionName);
		} catch (Exception e) {
			versionName = "1.0.0";
			versionCode = 0;
			channel = "";
		}
	}

	public int getResourceColor(int colorRes) {
		return mApplication.getResources().getColor(colorRes);
	}

	public static int fromXHDPItoDeviceScale(int dp) {
		return ((int) ((dp / 3) * density));
	}

	public static String formatString(String format, Object... args) {
		return String.format(Locale.US, format, args);
	}

	private void toast(String message) {
		Toast.makeText(mApplication, message, Toast.LENGTH_LONG).show();
	}

	public void toastSafe(final String message) {
		if (isRunInMainThread()) {
			toast(message);
		} else {
			post(new Runnable() {
				@Override
				public void run() {
					toast(message);
				}
			});
		}
	}

	public boolean post(Runnable runnable) {
		return mMainThreadHandler.post(runnable);
	}
}
